#ifndef LIBMUNIX_USART_H
#define LIBMUNIX_USART_H
/*******************************************************************************
 ** Name: usart.h                                                             **
 ** Description:              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the license.txt within              **
 ** this distribution or at http://www.munixos.net/licensing.                 **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $HOME/license.txt.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 **                                                                           **
 ** Copyright (c) 2009-2010  Barry Gian James <bjames@munixos.net>            **
 ** All rights reserved.                                                      **
 **                                                                           **
 ** Ref: $HeadURL$
 ******************************************************************************/
// Portions (C) 2011 OpenHouseware, LLC.
// All Rights Reserved

// $Id$
// Last Modified $DateTime$ by $Author$

#include <avr/interrupt.h>
#include "common.h"
#include "bus.h"

#if defined(__AVR_ATtiny2313__) || defined(__AVR_ATmega8__) || \
    defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || \
    defined(__AVR_ATmega8515__)
#define UCSR0B  UCSRB
#define RXCIE0  RXCIE
#define TXCIE0  TXCIE
#define RXEN0   RXEN
#define TXEN0   TXEN
#define UCSR0A  UCSRA
#define UCSR0B  UCSRB
#define UDRE0   UDRE
#define UDR0    UDR
#define U2X0    U2X
#define RXC0    RXC
#define TXC0    TXC
#define UBRR0L  UBRRL
#define UBRR0H  UBRRH
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega328P__)
    // this port nomenclature is the default
    // so we don't have to do anything
#elif defined(__AVR_ATxmega32A4__) || defined(__AVR_ATxmega64A3__) \
    || defined(__AVR_ATxmega128A3__) || defined(__AVR_ATxmega256A3__)

#endif

#define DEFAULT_RXBUFF_SZ	16
#define DEFAULT_TXBUFF_SZ	16

#define USART_TX    0x01
#define USART_RX    0x02

class USART : public Bus
{
public:
#if defined(XMEGA_DEFINED)
	USART(USART_t * u, uint32_t b, uint8_t d);
#endif
	USART(uint32 b, uint8 d, uint8 i = 0);
	USART(const USART & u) = delete;
	~USART();

	// instantiated virtual methods
        bool        Connect();
        void        SendByte(uint8 a,char c) { tx(c); }
        void        SendWord(uint8,wchar_t);
        char        RecvByte() { return rx(); }
        wchar_t     RecvWord();
        void        PowerUp();
        void        PowerDown();

        uint32      Baud() const { return baud; }

        void   EnableInterrupt(uint8 d) {
           if (d == USART_TX) UCSR0B |= (1<<RXCIE0);
           if (d == USART_RX) UCSR0B |= (1<<TXCIE0);
        }
        void	tx(char c) {
            while (!(UCSR0A & (1 << UDRE0)));
            UDR0 = c;

        }
        char	rx() {
            while (!(UCSR0A & (1 << RXC0)));
            return UDR0;

        }
        void     WriteRAMStr(const char * msg) {
            while (*msg != 0x00) {
                while(!(UCSR0A & (1<<UDRE0)));
                UDR0 = *(msg++);
            }
                //tx(*(msg++));
        }
        void     WriteLine(const char * msg) {
            while (pgm_read_byte(msg) != 0x00) {
                while(!(UCSR0A & (1<<UDRE0)));
                UDR0 = pgm_read_byte(msg++);
            }
                //tx(pgm_read_byte(msg++));
        }

	// Buffer methods
	inline void	AddToRecv(char c) { rxBuff->Put(c); }
	inline char	GetFromRecv() { return rxBuff->Get(); }
	inline char *	GetTXBuff() { return txBuff->Buff(); }
	inline char *	GetRXBuff() { return rxBuff->Buff(); }
	inline void	FlushTXBuff() { txBuff->Clear(); }
	inline void	FlushRXBuff() { rxBuff->Clear(); }

#if defined(USART_OPERATOR_STREAM)
        // Operator overloads for stream buffering-type layout
        USART & operator << (USART &);
        USART & operator << (bool);
        USART & operator << (uint8);    // same as uchar
        USART & operator << (uint16);
        USART & operator << (char);
        USART & operator << (char *);
        USART & operator << (int8_t);
        USART & operator << (int16_t);
#if defined(USART_STREAM_LONG)
        USART & operator << (int32_t);
        USART & operator << (uint32_t);
#endif
#if defined(USART_STREAM_DOUBLE)
        USART & operator << (float);
        USART & operator << (double);
#endif
#endif  /* USART_OPERATOR_STREAM */

private:
    uint32      baud;
    uint8       direction;
#if defined(XMEGA_DEFINED)
	USART_t *	usart;
#endif


};

#if defined(USART_OPERATOR_STREAM)
USART & endl(USART &);
// operator overloading with implicit type conversion
USART & operator << (USART &,char);
USART & operator << (USART &,signed char);
USART & operator << (USART &, const unsigned char *);
USART & operator << (USART &, const signed char *);
USART & operator << (USART &, char const * m);
#endif

#endif  /* LIBMUNIX_USART_H */
